if not MobDamage then
  MobDamage = { };
end

MobDamage.Target = { };
MobDamage.Target.Frame = nil;
MobDamage.Target.FeedBack = nil;
MobDamage.Target.FontHeight = 30;

MobDamage.Console = { };
MobDamage.Console.Frame = nil;

MobDamage.ClassModifiers = { };
MobDamage.Modifiers = { };
MobDamage.TargetGuid = nil;
MobDamage.ShowWhenOutOfCombat = nil;
MobDamage.HideWhenOutOfCombat = nil;
MobDamage.InitializeConsoleWhenOutOfCombat = nil;
MobDamage.ConfigureConsoleWhenOutOfCombat = nil;

if not MobDamageOptions then
  MobDamageOptions = { };
end


-----------------------------
-- COMBAT TEXT DISPLAY CODE
-----------------------------

--MobDamage_original_TargetOnClick = nil;

MobDamageText = { };
MobDamageText["INTERRUPT"]	= TEXT(INTERRUPT);
MobDamageText["MISS"]		= TEXT(MISS);
MobDamageText["RESIST"]	    = TEXT(RESIST);
MobDamageText["DODGE"]		= TEXT(DODGE);
MobDamageText["PARRY"]		= TEXT(PARRY);
MobDamageText["BLOCK"]		= TEXT(BLOCK);
MobDamageText["EVADE"]		= TEXT(EVADE);
MobDamageText["IMMUNE"]	    = TEXT(IMMUNE);
MobDamageText["DEFLECT"]	= TEXT(DEFLECT);
MobDamageText["ABSORB"]	    = TEXT(ABSORB);
MobDamageText["REFLECT"]	= TEXT(REFLECT);

local _G = getfenv(0)
local bit_bor = _G.bit.bor
local bit_band = _G.bit.band
local tinsert = _G.tinsert
local tremove = _G.tremove
local math_floor = _G.math.floor
local string_gsub = _G.string.gsub
local gsub = _G.gsub
local strsub = _G.strsub

local COMBATLOG_OBJECT_AFFILIATION_MINE = _G.COMBATLOG_OBJECT_AFFILIATION_MINE;
local COMBATLOG_OBJECT_REACTION_FRIENDLY = _G.COMBATLOG_OBJECT_REACTION_FRIENDLY;
local COMBATLOG_OBJECT_CONTROL_PLAYER = _G.COMBATLOG_OBJECT_CONTROL_PLAYER;
local COMBATLOG_OBJECT_TYPE_ME = bit_bor(COMBATLOG_OBJECT_TYPE_PLAYER, COMBATLOG_OBJECT_TYPE_OBJECT);
local COMBATLOG_OBJECT_TARGET = COMBATLOG_OBJECT_TARGET;

MobDamage.OnLoad = function()
  MobDamage.Target.FeedBack = TargetHitIndicator;
	
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("PLAYER_TARGET_CHANGED");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	
	this:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
	
	--Set up the slash command
	SLASH_MobDamage1 = "/mdmg";
	SlashCmdList["MobDamage"] = MobDamage.SlashHandler;
end

MobDamage.OnEvent = function(...)
  if event == "VARIABLES_LOADED" then
    MobDamage.InitializeVariables();
    if InCombatLockdown() == nil then
    	MobDamage.InitializeConsole();
    else
    	MobDamage.InitializeConsoleWhenOutOfCombat = true;
    end
    MobDamage.LoadModifiers();
    return;
  end
  
  if not MobDamageOptions["enabled"] then
    return;
  end
  
  if event == "PLAYER_TARGET_CHANGED" then
    if UnitExists("target") then
      MobDamage.TargetGuid = UnitGUID("target");
    else
      MobDamage.TargetGuid = nil;
    end
    MobDamage.UpdateConsoleVisibility();
    return;
  end
  
  if event == "PLAYER_REGEN_DISABLED" then
  	if InCombatLockdown() == nil then
  		if MobDamage.InitializeConsoleWhenOutOfCombat then
  			MobDamage.InitializeConsole();
  		end
  		
  		if MobDamage.ConfigureConsoleWhenOutOfCombat then
  			MobDamage.ConfigureConsole();
  		end
  		
	  	if MobDamage.ShowWhenOutOfCombat then
	  		if UnitExists("target") then
	  			MobDamage.Console.Frame:Show();
	  		end
	  		MobDamage.ShowWhenOutOfCombat = nil;
	  	elseif MobDamage.HideWhenOutOfCombat then
  			MobDamage.Console.Frame:Hide();
  			MobDamage.HideWhenOutOfCombat = nil;
	  	end
	  end
  end
  
  if event == "COMBAT_LOG_EVENT_UNFILTERED" then
  	MobDamage.CombatLogEvent(...);
  end
  
end

MobDamage.UpdateConsoleVisibility = function()
  if MobDamageOptions["showconsole"] and UnitExists("target") then
  	if InCombatLockdown() == nil then
  		MobDamage.Console.Frame:Show();
  	else
  		MobDamage.HideWhenOutOfCombat = nil;
  		MobDamage.ShowWhenOutOfCombat = true;
  	end
  else
    if InCombatLockdown() == nil then
    	MobDamage.Console.Frame:Hide();
    else
    	MobDamage.ShowWhenOutOfCombat = nil;
    	MobDamage.HideWhenOutOfCombat = true;
    end
  end
end

MobDamage.CombatLogEvent = function(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  if dstGUID ~= MobDamage.TargetGuid or
     bit_band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == 0 or
     bit_band(srcFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) == 0 or
     bit_band(srcFlags, COMBATLOG_OBJECT_CONTROL_PLAYER) == 0 or
     bit_band(srcFlags, COMBATLOG_OBJECT_TYPE_ME) == 0 then
	  return;
	end
	
	local spellId, spellSchool, missType, extraAmount, powerType;	
	-- Damage standard order
	local amount, school, resisted, blocked, absorbed, critical, glancing, crushing;
	local subVal = strsub(event, 1, 5)
	
	local showEvent, combatEvent, combatAmount, combatReduced, combatCrit, combatSchool, combatSpellName;
	
	-- Break out the arguments into variable
	if ( event == "SWING_DAMAGE" ) and MobDamageOptions["WHITEDAMAGE"] then 
		-- Damage standard
		amount, school, resisted, blocked, absorbed, critical, glancing, crushing = ...

		showEvent = true;
		combatEvent = "WOUND";
		combatCrit = critical;
		combatAmount = amount;
		combatSchool = CombatLog_String_SchoolString(school);
	elseif ( event == "SWING_MISSED" ) then 
		-- Damage standard
		missType = ...
		
		showEvent = true;
		combatEvent = missType;
		combatAmount = 0;
	elseif ( subVal == "SPELL" ) and MobDamageOptions["SPELLS"] then	-- Spell standard arguments
		spellId, combatSpellName, spellSchool = ...;
		combatSchool = CombatLog_String_SchoolString(spellSchool);

		if ( event == "SPELL_DAMAGE" ) then
			-- Damage standard
			amount, school, resisted, blocked, absorbed, critical, glancing, crushing = select(4, ...);

			showEvent = true;
			combatEvent = "WOUND";
			combatCrit = critical;
			combatAmount = amount;
		elseif ( event == "SPELL_MISSED" ) then 
			-- Miss type
			missType = select(4, ...);

			showEvent = true;
			combatEvent = missType;
			combatAmount = 0;
		elseif ( event == "SPELL_HEAL" ) then 
			-- Did the heal crit?
			amount, critical = select(4, ...);
			
			showEvent = true;
			combatEvent = "HEAL";
			combatCrit = critical;
			combatAmount = amount;
		elseif ( strsub(event, 1, 14) == "SPELL_PERIODIC" ) and MobDamageOptions["DOTS"] then
			
			if ( event == "SPELL_PERIODIC_MISSED" ) then
				-- Miss type
				missType = select(4, ...);
				
				showEvent = true;
				combatEvent = missType;
				combatAmount = 0;
			elseif ( event == "SPELL_PERIODIC_DAMAGE" ) then
				-- Damage standard
				amount, school, resisted, blocked, absorbed, critical, glancing, crushing = select(4, ...);

				showEvent = true;
				combatEvent = "WOUND";
				combatCrit = critical;
				combatAmount = amount;
			elseif ( event == "SPELL_PERIODIC_HEAL" ) then
				-- Did the heal crit?
				amount, critical = select(4, ...);
				
				showEvent = true;
				combatEvent = "HEAL";
				combatCrit = critical;
				combatAmount = amount;
			elseif ( event == "SPELL_PERIODIC_DRAIN" ) then
				-- Special attacks
				amount, powerType, extraAmount = select(4, ...);

				if powerType == -2 then
					showEvent = true;
					combatEvent = "WOUND";
					--combatCrit = critical;
					combatAmount = amount;
				end
			elseif ( event == "SPELL_PERIODIC_LEECH" ) then
				-- Special attacks
				amount, powerType, extraAmount = select(4, ...);

				if powerType == -2 then
					showEvent = true;
					combatEvent = "WOUND";
					--combatCrit = critical;
					combatAmount = amount;
				end
			elseif ( event == "SPELL_PERIODIC_ENERGIZE" ) then 
				amount, powerType = select(4, ...);
				
				if powerType == -2 then
					showEvent = true;
					combatEvent = "HEAL";
					--combatCrit = critical;
					combatAmount = amount;
				end			
			end
		elseif ( event == "SPELL_DRAIN" ) then		-- Special Spell effects
			-- Special attacks
			amount, powerType, extraAmount = select(4, ...);

			if powerType == -2 then
				showEvent = true;
				combatEvent = "WOUND";
				--combatCrit = critical;
				combatAmount = amount;
			end
		elseif ( event == "SPELL_LEECH" ) then
			-- Special attacks
			amount, powerType, extraAmount = select(4, ...);

			if powerType == -2 then
				showEvent = true;
				combatEvent = "WOUND";
				--combatCrit = critical;
				combatAmount = amount;
			end
		elseif ( event == "SPELL_EXTRA_ATTACKS" ) and MobDamageOptions["WHITEDAMAGE"] then
			-- Special attacks
			amount = select(4, ...);

			showEvent = true;
			combatEvent = "WOUND";
			--combatCrit = critical;
			combatAmount = amount;
		elseif ( subVal == "RANGE" ) then
			-- Shots are spells, technically
			spellId, combatSpellName, spellSchool = ...;
			combatSchool = CombatLog_String_SchoolString(spellSchool);
			if ( event == "RANGE_DAMAGE" ) then 
				-- Damage standard
				amount, school, resisted, blocked, absorbed, critical, glancing, crushing = select(4, ...);
	
				showEvent = true;
				combatEvent = "WOUND";
				combatCrit = critical;
				combatAmount = amount;
			end
		elseif ( event == "RANGE_MISSED" ) then 
			-- Damage standard
			missType = select(4, ...);

			showEvent = true;
			combatEvent = missType;
			combatAmount = 0;
		end
	elseif ( event == "DAMAGE_SHIELD" ) and MobDamageOptions["SHIELDS"] then	-- Damage Shields
		-- Spell standard, Damage standard
		spellId, combatSpellName, spellSchool, amount, school, resisted, blocked, absorbed, critical, glancing, crushing = ...;

		showEvent = true;
		combatEvent = "WOUND";
		combatCrit = critical;
		combatAmount = amount;
		combatSchool = CombatLog_String_SchoolString(spellSchool);
	elseif ( event == "DAMAGE_SHIELD_MISSED" ) and MobDamageOptions["SHIELDS"] then
		-- Spell standard, Miss type
		spellId, combatSpellName, spellSchool, missType = ...;

		showEvent = true;
		combatEvent = missType;
		combatAmount = 0;
		combatSchool = CombatLog_String_SchoolString(spellSchool);
	end
	
	if resisted then
		combatReduced = "RESIST";
	elseif blocked then
		combatReduced = "BLOCK";
	elseif absorbed then
		combatReduced = "ABSORB";
	elseif glancing then
		combatReduced = "DEFLECT";
	end
	
	if showEvent then
		MobDamage.OnCombatEvent(combatEvent, combatAmount, combatReduced, combatCrit, combatSchool, combatSpellName);
	end
end

-- event is WOUND, HEAL, IMMUNE, BLOCK, etc
-- reducedType is ABSORB, BLOCK, RESIST, etc
MobDamage.OnCombatEvent = function(event, amount, reducedType, crit, school, spellName)
  numAmount = tonumber(amount);
  if numAmount == nil then
    numAmount = 0;
  end

	local feedbackText = MobDamage.Target.FeedBack;
	local fontHeight = MobDamage.Target.FontHeight;
	local text = "";
	local r = 1.0;
	local g = 1.0;
	local b = 1.0;
	
	local HUGE = 1.5;
	local SMALL = 0.75;
	local TINY = 0.5;
	
	local modAmount = nil;
		
	if ( event == "WOUND" ) then
	  if ( amount ~= "0" ) then
		if (MobDamageOptions["minimumdamage"] ~= nil) and (numAmount < MobDamageOptions["minimumdamage"]) then
              return;
      	end
      
		if reduced then
		  fontHeight = fontHeight * SMALL;
		end
			
		if spellName ~= nil then
		  b = 0.0;
		end
			
		text = amount;
		modAmount = MobDamage.GetModifiedAmount(spellName, school, numAmount, crit);
	  elseif ( flags == "ABSORB" and MobDamageOptions["ABSORB"] == true) then
		fontHeight = fontHeight * SMALL;
		text = MobDamageText["ABSORB"];
	  elseif ( flags == "BLOCK" and MobDamageOptions["BLOCK"] == true ) then
		fontHeight = fontHeight * SMALL;
		text = MobDamageText["BLOCK"];
	  elseif ( flags == "RESIST" and MobDamageOptions["RESIST"] == true ) then
		fontHeight = fontHeight * SMALL;
		text = MobDamageText["RESIST"];
	  elseif ( flags == "REFLECT" and MobDamageOptions["REFLECT"] == true ) then
		text = MobDamageText["REFLECT"];
	  elseif MobDamageOptions["MISS"] == true then
		text = MobDamageText["MISS"];
	  else
	    return;
	  end
	elseif( event == "IMMUNE" ) then
	  if MobDamageOptions["IMMUNE"] ~= true then
		return;
	  end
	  fontHeight = fontHeight * TINY;
	  text = MobDamageText["IMMUNE"];
	elseif ( event == "BLOCK" ) then
	  if MobDamageOptions["BLOCK"] ~= true then
	    return;
	  end
	  fontHeight = fontHeight * SMALL;
	  text = MobDamageText[event];
	elseif ( event == "HEAL" ) then
	  if numAmount == 0 then
	    return;
	  end
	  
	  if (MobDamageOptions["minimumheal"] ~= nil) and (numAmount < MobDamageOptions["minimumheal"]) then
      	return;
      end
    
	  modAmount = MobDamage.GetModifiedAmount(spellName, 7, numAmount, crit);
	  text = amount;
		r = 0.0;
		g = 1.0;
		b = 0.0;
	else
	  if MobDamageOptions[event] ~= true then
	    return;
	  end
	  text = MobDamageText[event];
	end

	MobDamage.Target.StartTime = GetTime();
	
	feedbackText:SetTextHeight(fontHeight);
	feedbackText:SetText(text);
	feedbackText:SetTextColor(r, g, b);
	feedbackText:SetAlpha(1.0);
	feedbackText:Show();
	
	if MobDamageOptions["showconsole"] == true then
	  if amount ~= nil and modAmount ~= nil then
	    text = amount .. " (" .. modAmount .. ")";
	  end
	  MobDamage.Console.Frame:AddMessage(text, r, g, b);
	end
end

MobDamage.OnUpdate = function(frame, elapsed)
	local feedbackText = MobDamage.Target.FeedBack;
	if ( feedbackText:IsVisible() ) then
		local elapsedTime = GetTime() - MobDamage.Target.StartTime;
		local fadeInTime = MobDamageOptions["fadeintime"];
		if ( elapsedTime < fadeInTime ) then
			local alpha = (elapsedTime / fadeInTime);
			feedbackText:SetAlpha(alpha);
			return;
		end
		local holdTime = MobDamageOptions["holdtime"];
		if ( elapsedTime < (fadeInTime + holdTime) ) then
			feedbackText:SetAlpha(1.0);
			return;
		end
		local fadeOutTime = MobDamageOptions["fadeouttime"];
		if ( elapsedTime < (fadeInTime + holdTime + fadeOutTime) ) then
			local alpha = 1.0 - ((elapsedTime - holdTime - fadeInTime) / fadeOutTime);
			feedbackText:SetAlpha(alpha);
			return;
		end
		feedbackText:Hide();
	end
end

------------------------------
-- Console functions
------------------------------

MobDamage.InitializeConsole = function(visible)
	MobDamage.Console.Frame = getglobal("MobDamageConsole");
	if MobDamage.Console.Frame ~= nil then
	  MobDamage.Console.Frame:SetMaxLines(MobDamageOptions["consolelines"]);
	  MobDamage.Console.Frame:SetFading(true);
	  MobDamage.Console.Frame:SetFadeDuration(MobDamageOptions["fadeduration"]);
	  
	  MobDamage.Console.FrameBackground = getglobal("MobDamageConsoleBackground");
	  if MobDamage.Console.FrameBackground ~= nil then
	    MobDamage.Console.FrameBackground:SetVertexColor(0,0,0);
	    MobDamage.Console.FrameBackground:SetAlpha(MobDamageOptions["consolealpha"]/100.0);
	  end
	  
	  if (MobDamageOptions["showconsole"] == true) and UnitExists("target") then
	    MobDamage.Console.Frame:Show();
	  else
	    MobDamage.Console.Frame:Hide();
	  end
	end
end

MobDamage.OnMouseWheel = function(value)
   if ( value > 0 ) then
      if IsShiftKeyDown() then
         MobDamage.Console.Frame:ScrollToTop()
      elseif IsControlKeyDown() then
         MobDamage.Console.Frame:ScrollUp()
         MobDamage.Console.Frame:ScrollUp()
         MobDamage.Console.Frame:ScrollUp()
      else
         MobDamage.Console.Frame:ScrollUp()
      end
   elseif ( value < 0 ) then
      if IsShiftKeyDown() then
         MobDamage.Console.Frame:ScrollToBottom()
      elseif IsControlKeyDown() then
         MobDamage.Console.Frame:ScrollDown()
         MobDamage.Console.Frame:ScrollDown()
         MobDamage.Console.Frame:ScrollDown()
      else
         MobDamage.Console.Frame:ScrollDown()
      end
   end
end

MobDamage.SetConsoleAlpha = function(alphaValue)
  if alphaValue == nil then
    return;
  end
  if alphaValue < 0 or alphaValue > 100 then
    return;
  end
  
  MobDamageOptions["consolealpha"] = alphaValue;
  if MobDamage.Console.FrameBackground ~= nil then
    MobDamage.Console.FrameBackground:SetAlpha(MobDamageOptions["consolealpha"]/100.0);
  end
end

MobDamage.ResetConsolePosition = function()
  if InCombatLockdown() == nil then
    if MobDamage.Console.Frame ~= nil then
      MobDamage.Console.Frame:ClearAllPoints();
      MobDamage.Console.Frame:SetPoint("TOPLEFT", "MobDamage_TargetTextFrame", "TOPRIGHT", 130, 0);
    end
  else
    MobDamage.Print(MOBDAMAGE_FAILED_RESET);
  end
end

-----------------------------
-- MOD CONFIGURATION CODE
-----------------------------

MobDamage.Print = function(msg) --*
	if (DEFAULT_CHAT_FRAME) then
		DEFAULT_CHAT_FRAME:AddMessage(msg, 1.0, 1.0, 1.0);
	end
end

MobDamage.SlashHandler = function(command) --*
	local i,j, cmd, param = string.find(command, "^([^ ]+) (.+)$");

	-- nil prevention
	if (cmd == nil) then cmd = command; end
	if (not cmd) then cmd = command; end
	if (not cmd) then cmd = ""; end
	if (not param) then param = ""; end
	
	local upperCmd = string.upper(cmd);
	if (upperCmd == "ON") then
		MobDamageOptions["enabled"] = true;
		MobDamage.Print(MOBDAMAGE_ENABLED);
	elseif (upperCmd == "OFF") then
		MobDamageOptions["enabled"] = nil;
		MobDamage.Print(MOBDAMAGE_DISABLED);
  elseif (upperCmd == "CONSOLE") then
    local visible = (MobDamageOptions["showconsole"] == nil);
    MobDamage.SetConsoleVisibility(visible);
    if MobDamageOptions["showconsole"] then
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["console"] ..  MOBDAMAGE_OPTIONS_ON);
    else
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["console"] ..  MOBDAMAGE_OPTIONS_OFF);
    end
  elseif (upperCmd == "RESET") then
     MobDamage.ResetConsolePosition();
  elseif (upperCmd == "LOCK") then
    local val = MobDamageOptions["consolelocked"];
    if val == true then
      val = nil;
    else
      val = true;
    end
    MobDamage.SetConsoleLock(val);
  elseif (string.sub(upperCmd, 1, 5) == "ALPHA") then
    if string.len(param) > 0 then
      local alphaValue = tonumber(param);
      MobDamage.SetConsoleAlpha(alphaValue);
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["ALPHACHANGE"] .. alphaValue .. "%");
    end
  elseif upperCmd == "MODIFY" then
    if MobDamageOptions["modifiers"] then
      MobDamageOptions["modifiers"] = nil;
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["modifiers"] .. MOBDAMAGE_OPTIONS_OFF);
    else
      MobDamageOptions["modifiers"] = true;
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["modifiers"] .. MOBDAMAGE_OPTIONS_ON);
    end
  elseif upperCmd == "MIND" then
    numParam = tonumber(param);
    MobDamageOptions["minimumdamage"] = numParam;
    if numParam ~= nil then
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["minimumdamage"] .. tostring(numParam));
    else
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["minimumdamage"] .. MOBDAMAGE_OPTIONS_OFF);
    end
   elseif upperCmd == "MINH" then
    numParam = tonumber(param);
    MobDamageOptions["minimumheal"] = numParam;
    if numParam ~= nil then
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["minimumheal"] .. tostring(numParam));
    else
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["minimumheal"] .. MOBDAMAGE_OPTIONS_OFF);
    end
  elseif MOBDAMAGE_OPTIONSDISPLAY[upperCmd] ~= nil then
    if MobDamageOptions[upperCmd] == true then
      MobDamageOptions[upperCmd] = nil;
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY[upperCmd] .. MOBDAMAGE_OPTIONS_OFF);
    else
      MobDamageOptions[upperCmd] = true;
      MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY[upperCmd] .. MOBDAMAGE_OPTIONS_ON);
    end
  elseif ((cmd == "") or (cmd == "help")) then
	  MobDamage.Print(MOBDAMAGE_USEAGE);
	end
end

MobDamage.SetBooleanOption = function(option, on)
  local setting = nil;
  if on then
    setting = true;
  end
  MobDamageOptions[option] = setting;
end

MobDamage.SetOption = function(option, on)
  MobDamageOptions[option] = setting;
end

MobDamage.SetConsoleVisibility = function(visible)
  local show = nil;
  if visible then
    show = true;
  end

  MobDamageOptions["showconsole"] = show;
  local showConsoleCheck = getglobal("MobDamageOptionPanelshowconsole");
  if showConsoleCheck then
    showConsoleCheck:SetChecked(show);
  end
  MobDamage.UpdateConsoleVisibility();
end

MobDamage.LoadOptions = function(frame)
  if frame then
    local frameName = frame:GetName();
    local frameItem = nil;
    for key, val in pairs(MobDamageOptions) do
      frameItem = getglobal(frameName..key);
      if frameItem ~= nil then
        if frameItem:IsFrameType("CheckButton") then
          frameItem:SetChecked(val);
	      end
      end
    end
    frameItem = getglobal(frameName.."consolealpha");
    if frameItem ~= nil then
      frameItem:SetMinMaxValues(0, 100);
      frameItem:SetValueStep(1);
      frameItem:SetValue(MobDamageOptions["consolealpha"]);
    end
  end
end

MobDamage.InitializeVariables = function()
  if MobDamageOptions == nil then
    MobDamageOptions = { };
  end
  --fade and console settings
  MobDamage.CheckBooleanVariable("enabled", true);
  MobDamage.CheckBooleanVariable("showconsole", nil);
  MobDamage.CheckVariable("consolelines", 50);
  MobDamage.CheckVariable("fadeduration", 120);
  MobDamage.CheckVariable("fadeintime", 0.3);
  MobDamage.CheckVariable("holdtime", 0.9);
  MobDamage.CheckVariable("fadeouttime", 0.4);
  MobDamage.CheckVariable("consolealpha", 25);
  MobDamage.CheckBooleanVariable("consolelocked", nil);
  MobDamage.CheckBooleanVariable("modifiers", true);
  MobDamage.CheckVariable("minimumdamage", nil);
  MobDamage.CheckVariable("minimumheal", nil);
  --event settings
  MobDamage.CheckBooleanVariable("DODGE", true);
  MobDamage.CheckBooleanVariable("PARRY", true);
  MobDamage.CheckBooleanVariable("BLOCK", true);
  MobDamage.CheckBooleanVariable("MISS", true);
  MobDamage.CheckBooleanVariable("RESIST", true);
  MobDamage.CheckBooleanVariable("ABSORB", true);
  MobDamage.CheckBooleanVariable("IMMUNE", true);
  MobDamage.CheckBooleanVariable("DEFLECT", true);
  MobDamage.CheckBooleanVariable("REFLECT", true);
  MobDamage.CheckBooleanVariable("EVADE", true);
  MobDamage.CheckBooleanVariable("WHITEDAMAGE", true);
  MobDamage.CheckBooleanVariable("SPELLS", true);
  MobDamage.CheckBooleanVariable("SHIELDS", true);
  MobDamage.CheckBooleanVariable("DOTS", true);
  
  if InCombatLockdown() == nil then
  	MobDamage.ConfigureConsole();
  else
  	MobDamage.ConfigureConsoleWhenOutOfCombat = true;
  end
end

MobDamage.ConfigureConsole = function()
	if MobDamage.Console.Frame ~= nil then
    if MobDamageOptions["height"] ~= nil then
      MobDamage.Console.Frame:SetHeight(MobDamageOptions["height"]);
    end
    if MobDamageOptions["width"] ~= nil then
      MobDamage.Console.Frame:SetWidth(MobDamageOptions["width"]);
    end
    
    local x = MobDamageOptions["x"];
    local y = MobDamageOptions["y"];
    if x ~= nil and y ~= nil then
      MobDamage.Console.Frame:ClearAllPoints();
      MobDamage.Console.Frame:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", x, y);
    end
  end
end

MobDamage.CheckVariable = function(variable, value)
  if MobDamageOptions[variable] == nil then
    MobDamageOptions[variable] = value;
  end
end

MobDamage.CheckBooleanVariable = function(variable, value)
  if MobDamageOptions[variable] ~= true then
    MobDamageOptions[variable] = value;
  end
end

MobDamage.SaveSize = function()
  if MobDamage.Console.Frame ~= nil then
    MobDamageOptions["height"] = MobDamage.Console.Frame:GetHeight();
    MobDamageOptions["width"] = MobDamage.Console.Frame:GetWidth();    
  end
end

MobDamage.SavePosition = function()
  if MobDamage.Console.Frame ~= nil then
    MobDamageOptions["x"] = MobDamage.Console.Frame:GetLeft();
    MobDamageOptions["y"] = MobDamage.Console.Frame:GetTop();
  end
end

MobDamage.OffOrOn = function(val)
  if (val == nil) or (val == 0) then
    return MOBDAMAGE_OPTIONS_OFF;
  else
    return MOBDAMAGE_OPTIONS_ON;
  end
end

MobDamage.SetConsoleLocks = function(lock)
  local locked = nil;
  if lock then
    locked = true;
  end
  MobDamage.Console.Locked = locked;
  MobDamageOptions["consolelocked"] = locked;
  MobDamage.Print(MOBDAMAGE_OPTIONSDISPLAY["lock"] .. MobDamage.OffOrOn(locked));
end

MobDamage.TranslateDamageSchool = function(text)
  return string.lower(text);
end

---------------------
-- Modifier Utilities
---------------------

_, MobDamage.PlayerClass = UnitClass("player");

MobDamage.GetModifiedAmount = function(spellName, hitType, amount, crit)  
  if (not MobDamageOptions["modifiers"]) or (MobDamage.ClassModifiers[MobDamage.PlayerClass] == nil) or (amount == nil) then
    return nil;
  end  
  local modifierSetting = nil;
    
  if spellName ~= nil then
    modifierSetting = MobDamage.GetModifierSetting(spellName);
  end  
  if modifierSetting ~= nil then
    if modifierSetting["CritOnly"] ~= nil then
      if crit ~= nil then
        return MobDamage.Round(amount * modifierSetting["Modifier"]);
      end
    else
      return MobDamage.Round(amount * modifierSetting["Modifier"]);
    end
  end
  
  if hitType ~= nil then
    modifierSetting = MobDamage.GetModifierSetting(hitType);
  end  
  if modifierSetting ~= nil then
    if modifierSetting["CritOnly"] ~= nil then
      if crit ~= nil then
        return MobDamage.Round(amount * modifierSetting["Modifier"]);
      end
    else
      return MobDamage.Round(amount * modifierSetting["Modifier"]);
    end
  end
  
  return nil;
end

MobDamage.Round = function(amount)
  return math_floor(amount + 0.5);
end

MobDamage.GetModifierSetting = function(modifyName)
  local lowerName = string.lower(modifyName);
  if lowerName ~= nil then
    return MobDamage.Modifiers[lowerName];
  end
  return nil;
end

MobDamage.LoadModifiers = function()
  if MobDamage.ClassModifiers ~= nil then
    local tabIndex = 0;
    local talentIndex = 0;
    local spellName = nil;
    local crits = true;
    local ranks = nil;
    local classTalents = MobDamage.ClassModifiers[MobDamage.PlayerClass];
    if type(classTalents) == "table" then
      --foreach talent setting in the class
      for talentSetting=1, getn(classTalents) do
        if classTalents[talentSetting] ~= nil and type(classTalents[talentSetting]) == "table" then
          tabIndex = classTalents[talentSetting][1];
          talentIndex = classTalents[talentSetting][2];
          spellName = string.lower(classTalents[talentSetting][3]);
          crits = classTalents[talentSetting][4];
          ranks = classTalents[talentSetting][5];
          
          local currentRank = 0;
          if tabIndex > 0 and tabIndex <= GetNumTalentTabs() and talentIndex > 0 and talentIndex <= GetNumTalents(tabIndex) then
            _, _, _, _, currentRank, _, _, _ = GetTalentInfo(tabIndex, talentIndex);
            if currentRank ~= nil and currentRank > 0 then
              local amount = tonumber(ranks[currentRank]);
              MobDamage.Modifiers[spellName] = { Modifier=amount, CritOnly=crits };
            end
          end
        end
      end --Talent setting loop
    end
  end
end
